#ifndef __WIZ_DATATYPE_NAME_HPP__SHANHAOBO_19800429__
#define __WIZ_DATATYPE_NAME_HPP__SHANHAOBO_19800429__

#include "../Base/Type/WizBaseTypeString.hpp"
#include "./StrHashTab/WizDataTypeStrHashTab.hpp"

namespace Wiz
{
    namespace Name
    {
        namespace Proxy
        {
            template<class DerivedT, class StringT, class IndexT>
            struct Type : public ::Wiz::StrHashTab::Proxy::Type<DerivedT, StringT, IndexT>
            {
            };
        }

        template<class ProxyT, int TotalNum = 65536, int ReservedNum = 1024>
        class Type
        {
            WIZ_DECLARE_CLASS_THIS(Type);
        protected:
            typedef ProxyT                                  tProxy;

            typedef ::Wiz::StrHashTab::Type<tProxy, TotalNum, ReservedNum>
                                                            tHashTab;
            typedef typename tHashTab::tString              tString;
            typedef typename tHashTab::tIndex               tIndex;

            typedef const tIndex                            tIndexConst;

            typedef const tString                           tConstString;
            typedef tString&                                tStringRef;
            typedef tString*                                tStringPtr;
            typedef tConstString&                           tConstStringRef;
            typedef tConstString*                           tConstStringPtr;
        public:
            enum
            {
                eTotalCapacity      = tHashTab::eTotalCapacity,
                eReservedNum        = tHashTab::eReservedNum,
                eNonReservedNum     = tHashTab::eNonReservedNum,
                eInvalidIndex       = tHashTab::eInvalidIndex
            };
        public:
            Type() : m_Index(eInvalidIndex)
            {
            }
            explicit Type(tConstStringRef Str)
            {
                Set(Str);
            }
            explicit Type(tIndex InIdx)
            {
                if (GetHashTab().IsValidIndex(InIdx))
                {
                    m_Index = InIdx;
                }
                else
                {
                    m_Index = eInvalidIndex;
                }
            }
            Type(tThisIn Nm) : m_Index(Nm.m_Index)
            {
            }
        public:
            ::Wiz::Void::Type Set(tConstStringRef InStr)
            {
                m_Index = GetHashTab().AddString(InStr);
            }
            ::Wiz::Void::Type Set(tConstStringRef InStr, tIndexConst InReservedIndex)
            {
                m_Index = GetHashTab().AddStringByReservedHashCode(InStr, InReservedIndex);
            }
        public:
            ::Wiz::Bool::Type IsValid() const
            {
                return GetHashTab().IsValidIndex(m_Index);
            }
            ::Wiz::Bool::Type NotValid() const
            {
                return GetHashTab().IsValidIndex(m_Index) == ::Wiz::Bool::False;
            }
        public:
            friend ::Wiz::Bool::Type operator==(tThisIn A, tThisIn B)
            {
                return A.m_Index == B.m_Index;
            }
            friend ::Wiz::Bool::Type operator==(tThisIn A, tIndex B)
            {
                return A.m_Index == B;
            }
            friend ::Wiz::Bool::Type operator==(tThisIn A, tConstStringRef B)
            {
                tConstStringPtr StrPtr = GetStringPtr(A.m_Index);
                if (::Wiz::IsValidPtr(StrPtr))
                {
                    return *StrPtr == B;
                }
                return false;
            }
        public:
            friend ::Wiz::Bool::Type operator<(tThisIn A, tThisIn B)
            {
                return A.m_Index < B.m_Index;
            }
            friend ::Wiz::Bool::Type operator<(tThisIn A, tIndex B)
            {
                return A.m_Index < B;
            }
            friend ::Wiz::Bool::Type operator<(tThisIn A, tConstStringRef B)
            {
                tConstStringPtr StrPtr = GetStringPtr(A.m_Index);
                if (::Wiz::IsValidPtr(StrPtr))
                {
                    return *StrPtr < B;
                }
                return false;
            }
        public:
            ::Wiz::Bool::Type GetStr(tStringRef OutStr) const
            {
                return GetString(OutStr, m_Index);
            }
        protected:
            static tHashTab& GetHashTab()
            {
                static tHashTab s_HashTab;
                return s_HashTab;
            }
            static WIZ_INLINE tConstStringPtr GetStringPtr(tIndex InIdx)
            {
                return GetHashTab().GetStringPtr(InIdx);
            }
            static WIZ_INLINE ::Wiz::Bool::Type GetString(tStringRef OutStr, tIndex InIdx)
            {
                tConstStringPtr StrPtr = GetStringPtr(InIdx);
                if (::Wiz::IsValidPtr(StrPtr))
                {
                    OutStr = *StrPtr;
                    return ::Wiz::Bool::True;
                }

                return ::Wiz::Bool::False;
            }
        protected:
            tIndex          m_Index;
        };  /// end of class Type
    } /// end of namespace Name
} /// end of namespace Wiz

#endif /*__WIZ_DATATYPE_NAME_HPP__SHANHAOBO_19800429__*/
